---
id: efcore-recommend
title: 9.29 EFCore 最佳实践
sidebar_label: 9.29 EFCore 最佳实践
---

## 9.29.1 EFCore 高性能

在 `Furion` 框架，默认推荐使用 `EFCore` 操作数据库，但很多朋友对 `EFCore` 使用不当，特意编写此文档说明。

- 尽可能的采用 `IRepository/IRepository<TEntity>` 仓储方式在构造函数中初始化，**避免使用 `Db.GetRepository<TEntity>` 方式**。
- 请以**异步方式**调用所有数据访问 api。
- 检索的数据不是必需的。 编写查询以**仅返回当前 HTTP 请求所必需的数据**。
- 如果数据可以接受，请考虑**缓存经常访问的从数据库或远程服务检索的数据**。 使用 MemoryCache 或 microsoft.web.distributedcache ，具体取决于方案。
- **尽量减少网络往返次数**。 目标是使用单个调用而不是多个调用来检索所需数据。
- **如果当前请求只有数据查询，请使用无跟踪查询方式**。
- **如果请求中含有操作数据时，请不要在 Entity Framework Core 中使用无跟踪查询**。 EF Core 可以更有效地返回无跟踪查询的结果。 筛选和聚合 LINQ 查询（例如， .Where 使用.Select、或.Sum 语句），以便数据库执行筛选。
- 对于需要进行复杂逻辑计算查询数据情况，请尽可能在返回查询后再在客户端计算。
- **不要对集合使用投影查询**，这可能会导致执行 "N + 1" 个 SQL 查询。
- 使用 ·DbContextPool· 池来管理 DbContext，类似 ADO.NET 的连接池。
- 手动或显式编译的查询 API，允许应用程序缓存查询转换，使其可仅被计算一次并执行多次。

```cs
// Create an explicitly compiled query
private static Func<CustomerContext, int, Customer> _customerById =
    EF.CompileQuery((CustomerContext db, int id) =>
        db.Customers
            .Include(c => c.Address)
            .Single(c => c.Id == id));

// Use the compiled query by invoking it
using (var db = new CustomerContext())
{
   var customer = _customerById(db, 147);
}
```

## 9.29.2 反馈与建议

:::note 与我们交流

给 Furion 提 [Issue](https://gitee.com/dotnetchina/Furion/issues/new?issue)。

:::
